package com.example.demo.cbhs;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.context.xls.DefaultXlsReadContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.StringUtils;
import com.example.demo.model.BizInfo;
import com.example.demo.model.CalculateData;
import com.example.demo.model.DestinationPortCost;
import com.example.demo.model.LoadPortCost;
import com.example.demo.service.DeliveryPriceService;
import com.example.demo.utils.BigDecimalCollector;
import com.example.demo.utils.BigDecimalUtils;
import com.example.demo.utils.CalculateUtils;
import com.example.demo.utils.DataMappingUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author linjingze
 * @date 2023/12/18 11:30 AM
 */
public class CalculateListener extends AnalysisEventListener<Map<Integer, String>> {

    private CalculateData calculateData = new CalculateData();
    private List<Map<Integer, String>> dataList = new ArrayList<>();

    private String sheetName;

    BigDecimal UNKNOW_PRICE = new BigDecimal("99999999");

    private CalculateConfig calculateConfig;

    public CalculateListener(CalculateConfig calculateConfig) {
        this.calculateConfig = calculateConfig;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        calculateData.setDesc(headMap.get(1));
        calculateData.setAgentInfo(headMap.get(0));
        dataList.add(headMap);
        // 处理标题头
        this.sheetName = ((DefaultXlsReadContext) context).xlsReadSheetHolder().getReadSheet().getSheetName();
    }

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        // 处理每一行数据
        //System.out.println("解析到一条数据：" + data);
        dataList.add(data);
        // 根据实际情况处理数据（比如根据索引获取数据）
        // 例如，data.get(0) 将获取第一列的数据
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 全部解析完成后执行
        int loadPortIndex = -1;
        int dataStartIndex = -1;
        int dataEndIndex = -1;
        int destIndex = -1;
        for (int i = 0; i < dataList.size(); i++) {
            Map<Integer, String> data = dataList.get(i);
            String cs1 = data.get(0);
            if (StringUtils.isNotBlank(cs1)) {
                if (cs1.contains("汇率")) {
                    calculateData.setExchangeRate(new BigDecimal(data.get(1)));
                    continue;
                }
                if (cs1.contains("起运港应付成本(RMB)")) {
                    loadPortIndex = i + 1;
                    continue;
                }
                if (StringUtils.equals(cs1, "主单号")) {
                    dataStartIndex = i;
                    continue;
                }
                if (cs1.contains("目的港应付成本(RMB)")) {
                    destIndex = i+1;
                    continue;
                }
                if (cs1.contains("利润/亏损(RMB)")) {
                    calculateData.setAgentName(data.get(10));
                    continue;
                }


            }
            if (StringUtils.isNotBlank(data.get(1)) && StringUtils.equals(data.get(1), "合计")) {
                dataEndIndex = i;
                calculateData.setTeuDesc(data.get(9));
                continue;
            }
        }

        if (dataStartIndex != -1) {
            Map<Integer, String> dataHead = dataList.get(dataStartIndex);
            List<BizInfo> bizInfoList = new ArrayList<>();
            for (int i = dataStartIndex + 1; i < dataEndIndex; i++) {
                Map<Integer, String> map = dataList.get(i);
                if (i == dataStartIndex + 1) {
                    calculateData.setMainBizNo(map.get(1));
                }
                BizInfo bizInfo = new BizInfo();
                for (Map.Entry<Integer, String> e : dataHead.entrySet()) {
                    String value = map.get(e.getKey());
                    DataMappingUtils.setFieldValue(bizInfo, e.getValue(), value);
                }
                bizInfo.setCustomerName(map.get(11));
                bizInfo.setRt(CalculateUtils.getRT(bizInfo.isTaxFarming(), bizInfo.getWeight(), bizInfo.getVolume()));
                //bizInfo.setUseBoard(CalculateUtils.getUseBoard(bizInfo.getVolume()));
                bizInfoList.add(bizInfo);
            }
            BigDecimal exchangeRate = calculateData.getExchangeRate();
            BigDecimal headBsPrice = calculateConfig.getBsHeadPrice();
            BigDecimal unBsHeadPrice = calculateConfig.getUnBsHeadPrice();
            Map<String, List<BizInfo>> wMap = bizInfoList.stream()
                    .peek(s -> {
                        if (StringUtils.isBlank(s.getWarehouse())) {
                            s.setDeliveryPrice(UNKNOW_PRICE);
                        }
                    })
                    .filter(s -> StringUtils.isNotBlank(s.getWarehouse()))
                    .peek(s -> {
                        if (s.getWarehouse().contains("头程仓")) {
                            s.setDeliveryPrice(BigDecimal.ZERO);
                            s.setUseBoard(CalculateUtils.getUseBoard(s.getVolume()));
                            s.setRtPrice(CalculateUtils.getPrice(s.isTaxFarming(),
                                    s.getDeliveryPrice(), exchangeRate, s.getRt(), headBsPrice, unBsHeadPrice));
                        }
                    })
                    .filter(s -> !s.getWarehouse().contains("头程仓"))
                    .peek(s -> {
                        String newWarehouse = s.getWarehouse().replaceAll("[^A-Za-z0-9]", "");
                        s.setNewWarehouse(newWarehouse);
                    })
                    .collect(Collectors.groupingBy(BizInfo::getNewWarehouse));

            String area = calculateConfig.getArea();

            for (Map.Entry<String, List<BizInfo>> e : wMap.entrySet()) {
                List<BizInfo> list = e.getValue();
                String key = e.getKey();
                BigDecimal allVolume = e.getValue().stream().map(BizInfo::getVolume)
                        .collect(BigDecimalCollector.toSum());
                BigDecimal allUseBoard = CalculateUtils.getUseBoard(allVolume);
                DeliveryPriceService deliveryPriceService = new DeliveryPriceService();
                BigDecimal deliveryPrice = deliveryPriceService.getDeliveryPrice(area, key, allUseBoard.intValue());
                if (deliveryPrice == null) {
                    list.forEach(s -> s.setDeliveryPrice(UNKNOW_PRICE));
                    continue;
                }
                if (list.size() > 1) {
                    BigDecimal price = BigDecimalUtils.div(deliveryPrice, allUseBoard);
                    for (int i = 0; i < list.size(); i++) {
                        BizInfo bizInfo = list.get(i);
                        BigDecimal singleBoard = CalculateUtils.getUseBoard(bizInfo.getVolume());
                        BigDecimal singleDeliveryPrice = deliveryPriceService.getDeliveryPrice(area, key, singleBoard.intValue());
                        bizInfo.setRtPrice(CalculateUtils.getPrice(bizInfo.isTaxFarming(),
                                singleDeliveryPrice, exchangeRate, bizInfo.getRt(), headBsPrice, unBsHeadPrice));
                        if (i == 0) {
                            bizInfo.setUseBoard(allUseBoard);
                        } else {
                            bizInfo.setUseBoard(BigDecimal.ZERO);
                        }
                        bizInfo.setDeliveryPrice(BigDecimalUtils.mul(bizInfo.getUseBoard(), price));
                    }
                } else {
                    BizInfo bizInfo = list.get(0);
                    bizInfo.setUseBoard(allUseBoard);
                    bizInfo.setDeliveryPrice(deliveryPrice);
                    bizInfo.setRtPrice(CalculateUtils.getPrice(bizInfo.isTaxFarming(),
                            bizInfo.getDeliveryPrice(), exchangeRate, bizInfo.getRt(), headBsPrice, unBsHeadPrice));
                }
            }
            BigDecimal p = BigDecimalUtils.add(calculateConfig.getHyfBasePrice(), new BigDecimal("65"), new BigDecimal("35"));
            calculateData.setHyfPrice(BigDecimalUtils.mul(p, exchangeRate));
            calculateData.setBizInfoList(bizInfoList);
        }

        if (loadPortIndex != -1) {
            Map<Integer, String> loadHeadMap = dataList.get(loadPortIndex);
            LoadPortCost loadPortCost = new LoadPortCost();
            calculateData.setLoadPortCost(loadPortCost);
            Map<Integer, String> loadDataMap = dataList.get(loadPortIndex+1);
            for (Map.Entry<Integer, String> e : loadHeadMap.entrySet()) {
                String value = e.getValue();
                Integer key = e.getKey();
                DataMappingUtils.setFieldValue(loadPortCost, value, loadDataMap.get(key));
            }
        }
        if (destIndex != -1) {
            DestinationPortCost destinationPortCost = new DestinationPortCost();
            calculateData.setDestinationPortCost(destinationPortCost);
            Map<Integer, String> destHeadMap = dataList.get(destIndex);
            Map<Integer, String> destDataMap = dataList.get(destIndex + 1);
            for (Map.Entry<Integer, String> e : destHeadMap.entrySet()) {
                String value = e.getValue();
                Integer key = e.getKey();
                DataMappingUtils.setFieldValue(destinationPortCost, value, destDataMap.get(key));
            }
        }
        DestinationPortCost destinationPortCost = calculateData.getDestinationPortCost();
        LoadPortCost loadPortCost = calculateData.getLoadPortCost();
        calculateData.setTrailerPrice(destinationPortCost.getPierpassPrice());
        calculateData.setBgf(loadPortCost.getBgfPrice());
        calculateData.setQgf(destinationPortCost.getQgfPrice());
        calculateData.setC5(destinationPortCost.getC5pmPrice());
        calculateData.setFda(destinationPortCost.getFdasbPrice());
    }

    public CalculateData getCalculateData() {
        return calculateData;
    }

    public String getSheetName() {
        return sheetName;
    }
}
